#include <windows.h>

#include "resource.h"

#include<conio.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>


   int level;
    int a=20;
	int b=180;
	int c=70;
	int d=200;
	HDC hDC;
	HDC hdc;
	HWND hwnd;
	PAINTSTRUCT Ps;

struct skip_list{

	int index;
	struct skip_list *next[MAXLEVEL];

}; 
struct skip_list *list, *tmp_ptr, *hold, *root, *new_node,*p,*prim;
int random_level();
void afisare(HWND hwnd)
{
	
	int i;
	char buf1[20];
	int x=120;
	if(root)
	{
		prim=root;
		prim=prim->next[1];
		for(i=MAXLEVEL-1;i>0;i--)
			{
				while(prim)
					{
				
						sprintf(buf1,"%d",prim->index);
						TextOut(hDC,20+x, 250,buf1,strlen(buf1));
						x=x+100;
						prim=prim->next[0];
					}
			}
	}
}

void afisare2()
{
	if(level==1)
		print1(hwnd,a,b,c,d);
	if(level==2)
		print2(hwnd,a,b,c,d);
	if(level==3)
		print3(hwnd,a,b,c,d);
	if(level==4)
	    print4(hwnd,a,b,c,d);
}
void desen(HWND hwnd)
{
	POINT Pt[10];
	POINT Pt1[10];
    POINT Pt2[10];
    POINT Pt3[10];
	HBRUSH hBrush1;
    RECT   r;
    hDC = GetDC(hwnd);

         SetRect(&r,30,80, 850, 300);
			 FillRect(hDC,&r,CreateSolidBrush(RGB(192,192,192)));
        
	     
		    Pt[0].x = 90;  Pt[0].y = 90;
            Pt[1].x = 790; Pt[1].y = 90;

            Pt1[0].x = 90; Pt1[0].y = 125;
            Pt1[1].x = 790; Pt1[1].y = 125;

            Pt2[0].x = 90; Pt2[0].y = 160;
            Pt2[1].x = 790;  Pt2[1].y = 160;

		    Pt3[0].x = 90; Pt3[0].y = 190;
            Pt3[1].x = 790; Pt3[1].y = 190;
	

			  Rectangle(hDC,30,80,80,200);
			  Rectangle(hDC,800,80,850,200);
			    Polygon(hDC,Pt,2);
				Polygon(hDC,Pt1,2);
		    	Polygon(hDC,Pt2,2);
				Polygon(hDC,Pt3,2);
        TextOut(hDC,30,110,"HEAD",4);
		TextOut(hDC,810,110,"NULL",4);
		EndPaint(hwnd, &Ps);
		UpdateWindow(hwnd);
}

void AddMenus(HWND hwnd)
{
	HMENU hMenubar;
	HMENU hMenu;
	HMENU hMenu1;
	hMenubar=CreateMenu();
	hMenu=CreateMenu();
	hMenu1=CreateMenu();

  AppendMenu(hMenu, MF_STRING, ID_NEW, "&New");
  AppendMenu(hMenu, MF_STRING, ID_OPEN, "&Open");
  AppendMenu(hMenu, MF_STRING, ID_EXIT, "&Exit");
  AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hMenu, "&File");
  SetMenu(hwnd, hMenubar);

  AppendMenu(hMenu1, MF_STRING, ID_ABOUT, "&About");
  AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hMenu1, "&Help");
  SetMenu(hwnd, hMenubar);
}


int init_list()
{
	
	int i;
	 a=20; b=180; c=70; d=200;
	new_node =(struct skip_list *)malloc(sizeof(struct skip_list));
	list=new_node;
	root=list;
	list->index=NULL;
	for(i=0;i<MAXLEVEL;i++)
	{
		list->next[i]=NULL;
	}
	
	return 1;
}

int search_list(int number)
{
	int i, count = 0, result;
	char again;
		if(number > 0) 
		{
			result = FALSE;
            list = root;
			for(i=MAXLEVEL-1;i>=0;i--)
			{
				if(i < MAXLEVEL-1)
				{ 
					list = tmp_ptr->next[i];
				} 
				while(list)
				{
					if(list->index > 0)
					{ 
						count++;
					} 
					if(list->index == number)
					{ 
						result = TRUE;
						break;
					} 
					if(list->index > number)
					{ 
						break;
					}
					tmp_ptr = list; 
					list = list->next[i];  

				}
				if(result == TRUE)
				{
					break; 
				}
			}
			if(result == FALSE)
			{ 
				MessageBox(NULL,"Valoara nu exista","Eroare",MB_OK);
			}
			else MessageBox(NULL,"Valoarea a fost gasita","Cautarea",MB_OK);
		} 
		else
			MessageBox(NULL,"Valoarea e prea mica","Eroare",MB_OK);  
	return TRUE;
}

void citeste3(HWND hwnd)
{
	int x;
	char *p=NULL;
	x = GetWindowTextLength(GetDlgItem(hwnd, ID_EDIT));
		if (x>0) 
			{
				    p=(char*)malloc(sizeof(char)*(x+1));
					GetDlgItemText(hwnd, ID_EDIT , p, x+1);
		    }
		delete_node(atoi(p));
}

void citeste2(HWND hwnd)
{

	int x;
	char *p=NULL;
	x = GetWindowTextLength(GetDlgItem(hwnd, ID_EDIT));
        if (x>0) 
        {
                p=(char*)malloc(sizeof(char)*(x+1));
                GetDlgItemText(hwnd, ID_EDIT , p, x+1);
        }
		search_list(atoi(p));
}

void citeste(HWND hwnd)
{
	
	int x;
	char *p=NULL;
	x = GetWindowTextLength(GetDlgItem(hwnd, ID_EDIT));
        if (x>0) 
        {
                p=(char*)malloc(sizeof(char)*(x+1));
                GetDlgItemText(hwnd, ID_EDIT , p, x+1);
        }
		input_data(atoi(p),hwnd);
}


int delete_node(int number)
{
	int i, result;
	char again;
		if(number > 0)
		{
			if(find_node(number) == TRUE)
			{
				result = FALSE;
				list = root;
				for(i=MAXLEVEL-1;i>=0;i--)
				{
					if(result == FALSE)
					{
						if(i < MAXLEVEL-1)
						{ 
							list = tmp_ptr->next[i];
						} 
						while(list)
						{
							if(list->index == number) 
							{
								result = TRUE;
								break;
							} 
							if(list->index > number)
							{
								break;
							}
							tmp_ptr = list; 
							list = list->next[i];
						}
					} 
					if (result == TRUE)
					{
						hold = tmp_ptr;
						tmp_ptr = tmp_ptr->next[i];
						if(tmp_ptr->index == list->index)
						{ 
							tmp_ptr = hold; 
						}
						tmp_ptr->next[i] = list->next[i];
					}
				}
				if(result ==  TRUE) 
				{ 
					free(list);
					MessageBox(NULL,"Valoarea a fost stearsa","Stergerea",MB_OK); 
				}
			} 
			else 
			{ 
				MessageBox(NULL,"Valoarea nu exista","Eroare",MB_OK);
			}
		}
		else 
		{
			MessageBox(NULL,"Valoarea este prea mica","Eroare",MB_OK); 
		}
	
	return TRUE;
}


void insert_fisier(char *filename,HWND hwnd)
{
	
	char data[123];
		char *c, *p, s[123];
	FILE *f=fopen(filename,"r");
	if(!f)
	{
		MessageBox(NULL,"Eroare la deschidera fisierului!","Error",MB_OK|MB_ICONERROR);
		return;
	}
	init_list();
	while(!feof(f))
	{
		fgets(s,100,f);
		p=strtok(s," \0");
		while(p)
		{
			strcpy(data,p);
			p=strtok(NULL," \0");
			input_data(atoi(data),hwnd);
		}
		
	}
	fclose(f);
}

int find_node(int index) {
	
	int i, result = FALSE;

	list = root;
	for(i=MAXLEVEL-1;i>=0;i--)
	{
		if(i < MAXLEVEL-1) 
		{
			list = tmp_ptr->next[i];
		} 
		while(list) 
		{
			if(list->index == index)
			{
				result = TRUE;
				break;
			}
			if(list->index > index) 
			{ 
				break;
			}
			tmp_ptr = list;
			list = list->next[i];
		}
		if(result == TRUE)
		{ 
			break;
		}
	}
	
	return result;
}

void nothing_input(FILE *fd)
{
	int ch;
	
	while( (ch = fgetc(fd)) != EOF && ch != '\n' );
}


int random_level() {
	int value = rand() % (MAXLEVEL - LOW + 1) + LOW;
	return value;
}

int input_data(int data,HWND hwnd)
{
	
	
	int  i, startlevel, found;
	char again;
		again = '\0';	
		a=a+100;
	c=c+100;
		if(data > 0 )
		{ 
			if(find_node(data) == FALSE)
			{				
				level = random_level();

				
				  for(i=MAXLEVEL-1; i>=0; i--) 
				  {
                    if(root->next[i] != NULL && i > level-1)
					{
                         startlevel = i;
                         break;                 
                    } else 
					{ 
						startlevel = level; 
					}  
				
                }
				list = root;  
				
				tmp_ptr = NULL;
				new_node = (struct skip_list *)malloc(sizeof(struct skip_list)); 
				for(i=startlevel-1; i>=0; i--)
				{
					found = FALSE;
					tmp_ptr = list->next[i];
					if(tmp_ptr) 
					{
						while(tmp_ptr)
						{
							if(tmp_ptr->index < data) 
							{
								list = tmp_ptr;
								if(tmp_ptr->next[i] != NULL)
								{
									tmp_ptr = tmp_ptr->next[i]; 
								} 
								else 
								{ 
									found = TRUE;
									tmp_ptr = NULL;
								}
							} 
							else
							{
								found = TRUE;
								break;
							}
						}
						
						if(found == TRUE && level-1 >= i)
						{
							list->next[i] = new_node;
							new_node->index = data;
							if(tmp_ptr == NULL)
							{ 
								new_node->next[i] = NULL; 
							}
							else
							{
								new_node->next[i] = tmp_ptr; 
							}
						}	
					
					}
					else 
					{
						list->next[i] = new_node;
						new_node->index = data;
						new_node->next[i] = tmp_ptr;
					}
					
				}
			} else
			{
				MessageBox(NULL,"Exista","Eroare",NULL);
				return 0;
			}
			
			if(new_node->index==data)
				{
				if(level==1)
					print1(hwnd,a,b,c,d);
				if(level==2)
					print2(hwnd,a,b,c,d);
				if(level==3)
					print3(hwnd,a,b,c,d);
				if(level==4)
	     			print4(hwnd,a,b,c,d);
			}

			
		}
	return TRUE;
}

void freelist()

{
	int i;
	p =(struct skip_list *)malloc(sizeof(struct skip_list));
	list=p;
	root=list;
	list->index=-1;
	for(i=0;i<MAXLEVEL;i++)
	{
		list->next[i]=NULL;
	}
	return 1;
	}

int count_node(int start, int stop) {
	int count = 0;
	tmp_ptr = root;
	while(tmp_ptr) {
		if(tmp_ptr->index > start && tmp_ptr->index < stop) { count++; }
		if(tmp_ptr->index > stop) break;
		tmp_ptr = tmp_ptr->next[0];
	}
	return count;
}


int print1(HWND hwnd,int a,int b,int c,int d)
{
	
	    hDC = GetDC(hwnd);
	    Rectangle(hDC,a,b,c,d);		 
		UpdateWindow(hwnd);
}

int print2(HWND hwnd,int a,int b,int c,int d)
{
	    
		 hDC = GetDC(hwnd);
	     Rectangle(hDC,a,b-30,c,d-30);	
		 Rectangle(hDC,a,b,c,d);	
}



int print3(HWND hwnd,int a,int b,int c,int d) 
{
	
		 hDC = GetDC(hwnd);
	     Rectangle(hDC,a,b-65,c,d-65);	
	     Rectangle(hDC,a,b-30,c,d-30);	
		 Rectangle(hDC,a,b,c,d);
}
int print4(HWND hwnd,int a,int b,int c,int d)
{
	
		 hDC = GetDC(hwnd);
	     Rectangle(hDC,a,b-100,c,d-100);	
	     Rectangle(hDC,a,b-65,c,d-65);	
	    Rectangle(hDC,a,b-30,c,d-30);	
		 Rectangle(hDC,a,b,c,d);
}



LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
 PAINTSTRUCT pntstruct;
	OPENFILENAME fon;  
		char szFileName[MAX_PATH] = "";
			
		char *buffer1;
		int buffer,i;


  switch(msg)
  {

    case WM_CREATE:
		hwndButton1 = CreateWindow(TEXT("button"), TEXT("Insert"),	WS_VISIBLE | WS_CHILD , 150,30, 80, 25, hwnd, (HMENU) ID_INSERT, NULL, NULL);  
		hwndButton = CreateWindow(TEXT("button"), TEXT("Delete"), WS_VISIBLE | WS_CHILD,  250,30, 80, 25,hwnd, (HMENU) ID_DELETE, NULL, NULL);
		hwndButton = CreateWindow(TEXT("button"), TEXT("Search"), WS_VISIBLE | WS_CHILD, 350,30, 80, 25, hwnd, (HMENU) ID_SEARCH, NULL, NULL);
		hwndButton = CreateWindow(TEXT("button"), TEXT("Refresh"), WS_VISIBLE | WS_CHILD, 450,30, 80, 25, hwnd, (HMENU) ID_REFRESH, NULL, NULL);
		hwndCombo = CreateWindow("combobox", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER ,30, 30, 100, 25, hwnd,(HMENU) ID_EDIT, NULL, NULL);

    	AddMenus(hwnd);

		break;


	case WM_COMMAND:	  
		   switch(LOWORD(wParam))
		   {     
				    if (HIWORD(wParam) == BN_CLICKED) 
					{
		   case ID_NEW:
			   if(MessageBox(hwnd,"Doriti o noua inserare?","New",MB_YESNO)==IDYES)
			   {
				   init_list();
				   desen(hwnd);
				   MessageBox(NULL,"Initializare completa","Initializare",MB_OK);
			   }
			   else
			   {
				   MessageBox(NULL,"eroare","Initializare",MB_OK);
			   }
			   break;
		   
		   case ID_OPEN:
			   if(MessageBox(hwnd,"Doriti sa adaugati date din fisier?","Nou",MB_YESNO | MB_ICONINFORMATION)==IDYES)
			   {
				   init_list();
				   desen(hwnd);
    			   hdc=GetDC(hwnd);
                                ZeroMemory(&fon, sizeof(fon));
                                fon.lStructSize = sizeof(fon); 
                                fon.hwndOwner = hwnd;
                                fon.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
                                fon.lpstrFile = szFileName;
                                fon.nMaxFile = MAX_PATH;
                                fon.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
                                fon.lpstrDefExt = "txt";
                                if(GetOpenFileName(&fon))
                                {
                                       insert_fisier(szFileName,hwnd);
                                }
                       
                        MessageBox (hwnd,"Lista a fost initializata.","NOU",MB_OK);                        
			  }
			   else
				   MessageBox(NULL,"eroare la deschiderea fisierului","eraore",NULL);
			   break;
       


			  case ID_ABOUT:
                       MessageBox(NULL, TEXT("SkipList Applet\nVersion 1.0\nCopyright(flo)2012"), TEXT("About.."), MB_OK );
               break;

		      case ID_EXIT:
				  freelist();
                      SendMessage(hwnd, WM_CLOSE, 0, 0);
               break;
					
			  case ID_INSERT:
				  if(root!=NULL)
				  {

				  buffer = GetWindowTextLength(GetDlgItem(hwnd, ID_EDIT));
				  if(buffer==0 || buffer <0)
				  {
					  MessageBox(hwnd,"Campul numar nu exista","Eroare",MB_OK);
					  return 0;
				  }
				  else
					  buffer1=(char *)malloc(sizeof(char )*(buffer+1));
				      GetDlgItemText(hwnd,ID_EDIT,buffer1,buffer+1);
				  for(i=0;i<buffer;i++)
				  {
					  if(isdigit(buffer1[i])==0)
					  {
						  MessageBox(hwnd,"Campul numar nu exista","Eroare",MB_OK);
						  return 0;
					  }
				  }
					
					  citeste(hwnd);
				  }
				  else
					  MessageBox(hwnd,"Nu e initializata","Eroare",NULL);
			   break;

			  case ID_SEARCH:
				  citeste2(hwnd);
	   		   break;


			  case ID_DELETE:
				  citeste3(hwnd);
		       break;
			   

			  case ID_REFRESH:
				afisare(hwnd);
				UpdateWindow(hwnd);
		       break;
					} 
		   }
		   break;
	case WM_DESTROY:
		freelist();
		PostQuitMessage(0);
	break;
	
  }
		  
  return DefWindowProc(hwnd, msg, wParam, lParam);

	}
	

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )
{
  MSG  msg ;    
  WNDCLASS wc = {0};
  HWND hwnd;



  wc.lpszClassName = TEXT( "windows" );
  wc.hInstance     = hInstance ;
  wc.hbrBackground = CreateSolidBrush(RGB(192,192,192));
  wc.lpfnWndProc   = WndProc ;
  wc.hCursor       = LoadCursor(0,IDC_ARROW);
  wc.style         = 0;



  RegisterClass(&wc);

  hwnd=CreateWindow( wc.lpszClassName, TEXT("SkipList Applet"),
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                220, 220, 880, 400, 0, 0, hInstance, 0);  

  if(hwnd == NULL)
  {
	  MessageBox(NULL,"Window Creation Failed!","Error",MB_OK);
	  return 0;
  }

  UpdateWindow(hwnd)  ;


  while( GetMessage(&msg, NULL, 0, 0))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return (int) msg.wParam;
}


